package org.testis.utils;

import org.testis.data.AtofModuleConstants;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 *
 * @author nurhat
 */
public class StringVerification
{

    /**
     * Checks and answers if the given string is whitespace,
     * empty ("") or <code>null</code>.
     *
     * <pre>
     * StringVerification.isBlank(null)    == true
     * StringVerification.isBlank("")      == true
     * StringVerification.isBlank(" ")     == true
     * StringVerification.isBlank(" abc")  == false
     * StringVerification.isBlank("abc ")  == false
     * StringVerification.isBlank(" abc ") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string is whitespace, empty
     *    or <code>null</code>
     *
     * @see #isEmpty(String)
     */
    public static boolean isBlank(String str)
    {
        int length;
        if ((str == null) || ((length = str.length()) == 0)) {
            return true;
        }
        for (int i = length - 1; i >= 0; i--) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }


    /**
     * Checks and answers if the given string is not empty (""),
     * not <code>null</code> and not whitespace only.
     *
     * <pre>
     * StringVerification.isNotBlank(null)    == false
     * StringVerification.isNotBlank("")      == false
     * StringVerification.isNotBlank(" ")     == false
     * StringVerification.isNotBlank(" abc")  == true
     * StringVerification.isNotBlank("abc ")  == true
     * StringVerification.isNotBlank(" abc ") == true
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string is not empty
     *    and not <code>null</code> and not whitespace only
     *
     * @see #isEmpty(String)
     */
    public static boolean isNotBlank(String str)
    {
        int length;
        if ((str == null) || ((length = str.length()) == 0)) {
            return false;
        }
        for (int i = length - 1; i >= 0; i--) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }


    /**
     * Checks and answers if the given string is empty ("") or <code>null</code>.
     *
     * <pre>
     * StringVerification.isEmpty(null)  == true
     * StringVerification.isEmpty("")    == true
     * StringVerification.isEmpty(" ")   == false
     * StringVerification.isEmpty("Hi ") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string is empty or <code>null</code>
     *
     * @see #isBlank(String)
     */
    public static boolean isEmpty(String str)
    {
        return (str == null) || (str.length() == 0);
    }


    /**
     * Checks and answers if the given string is not empty ("")
     * and not <code>null</code>.
     *
     * <pre>
     * StringVerification.isNotEmpty(null)  == false
     * StringVerification.isNotEmpty("")    == false
     * StringVerification.isNotEmpty(" ")   == true
     * StringVerification.isNotEmpty("Hi")  == true
     * StringVerification.isNotEmpty("Hi ") == true
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string is not empty and not <code>null</code>
     *
     * @see #isBlank(String)
     */
    public static boolean isNotEmpty(String str)
    {
        return (str != null) && (str.length() > 0);
    }


    /**
     * Checks and answers if the given string has at least the
     * specified minimum length.
     * Strings that are <code>null</code> or contain only blanks have length 0.
     *
     * <pre>
     * StringVerification.hasMinimumLength(null,  2) == false
     * StringVerification.hasMinimumLength("",    2) == false
     * StringVerification.hasMinimumLength(" ",   2) == false
     * StringVerification.hasMinimumLength("   ", 2) == false
     * StringVerification.hasMinimumLength("Hi ", 2) == true
     * StringVerification.hasMinimumLength("Ewa", 2) == true
     * </pre>
     *
     * @param str   the string to check
     * @param min   the minimum length
     * @return <code>true</code> if the length is greater or equal to the minimum,
     *     <code>false</code> otherwise
     */
    public static boolean hasMinimumLength(String str,
                                           int min)
    {
        int length = str == null ? 0 : str.trim().length();
        return min <= length;
    }


    /**
     * Checks and answers if the given string is shorter than
     * the specified maximum length.
     * Strings that are <code>null</code> or contain only blanks have length 0.
     *
     * <pre>
     * StringVerification.hasMaximumLength(null,  2) == true
     * StringVerification.hasMaximumLength("",    2) == true
     * StringVerification.hasMaximumLength(" ",   2) == true
     * StringVerification.hasMaximumLength("   ", 2) == true
     * StringVerification.hasMaximumLength("Hi ", 2) == true
     * StringVerification.hasMaximumLength("Ewa", 2) == false
     * </pre>
     *
     * @param str   the string to check
     * @param max   the maximum length
     * @return <code>true</code> if the length is less than or equal to the minimum,
     *     <code>false</code> otherwise
     */
    public static boolean hasMaximumLength(String str,
                                           int max)
    {
        int length = str == null ? 0 : str.trim().length();
        return length <= max;
    }


    /**
     * Checks and answers if the length of the given string is in the
     * bounds as specified by the interval [min, max].
     * Strings that are <code>null</code> or contain only blanks have length 0.
     *
     * <pre>
     * StringVerification.hasBoundedLength(null,  1, 2) == false
     * StringVerification.hasBoundedLength("",    1, 2) == false
     * StringVerification.hasBoundedLength(" ",   1, 2) == false
     * StringVerification.hasBoundedLength("   ", 1, 2) == false
     * StringVerification.hasBoundedLength("Hi ", 1, 2) == true
     * StringVerification.hasBoundedLength("Ewa", 1, 2) == false
     * </pre>
     *
     * @param str   the string to check
     * @param min   the minimum length
     * @param max   the maximum length
     * @return <code>true</code> if the length is in the interval,
     *     <code>false</code> otherwise
     * @throws IllegalArgumentException if min > max
     */
    public static boolean hasBoundedLength(String str,
                                           int min,
                                           int max)
    {
        if (min > max) {
            throw new IllegalArgumentException(
                "The minimum length must be less than or equal to the maximum length.");
        }
        int length = str == null ? 0 : str.trim().length();
        return (min <= length) && (length <= max);
    }


    // Character Validations **************************************************
    /**
     * Checks and answers if the given string contains only unicode letters.
     * <code>null</code> returns false,
     * an empty string ("") returns <code>true</code>.
     *
     * <pre>
     * StringVerification.isAlpha(null)   == false
     * StringVerification.isAlpha("")     == true
     * StringVerification.isAlpha("   ")  == false
     * StringVerification.isAlpha("abc")  == true
     * StringVerification.isAlpha("ab c") == false
     * StringVerification.isAlpha("ab2c") == false
     * StringVerification.isAlpha("ab-c") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string contains only unicode letters,
     *     and is non-<code>null</code>
    
     */
    public static boolean isAlpha(String str)
    {
        if (str == null) {
            return false;
        }
        for (int i = str.length() - 1; i >= 0; i--) {
            if (!Character.isLetter(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }


    /**
     * Checks and answers if the given string contains only unicode letters
     * and space (' ').
     * <code>null</code> returns false,
     * an empty string ("") returns <code>true</code>.
     *
     * <pre>
     * StringVerification.isAlphaSpace(null)   == false
     * StringVerification.isAlphaSpace("")     == true
     * StringVerification.isAlphaSpace("   ")  == true
     * StringVerification.isAlphaSpace("abc")  == true
     * StringVerification.isAlphaSpace("ab c") == true
     * StringVerification.isAlphaSpace("ab2c") == false
     * StringVerification.isAlphaSpace("ab-c") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string contains only unicode letters
     *     and space, and is non-<code>null</code>
    
     */
    public static boolean isAlphaSpace(String str)
    {
        if (str == null) {
            return false;
        }
        for (int i = str.length() - 1; i >= 0; i--) {
            char c = str.charAt(i);
            if (!Character.isLetter(c) && (c != ' ')) {
                return false;
            }
        }
        return true;
    }


    /**
     * Checks and answers if the given string contains only
     * unicode letters or digits.
     * <code>null</code> returns false,
     * an empty string ("") returns <code>true</code>.
     *
     * <pre>
     * StringVerification.isAlphanumeric(null)   == false
     * StringVerification.isAlphanumeric("")     == true
     * StringVerification.isAlphanumeric("   ")  == false
     * StringVerification.isAlphanumeric("abc")  == true
     * StringVerification.isAlphanumeric("ab c") == false
     * StringVerification.isAlphanumeric("ab2c") == true
     * StringVerification.isAlphanumeric("ab-c") == false
     * StringVerification.isAlphanumeric("123")  == true
     * StringVerification.isAlphanumeric("12 3") == false
     * StringVerification.isAlphanumeric("12-3") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string contains only unicode letters
     *     or digits, and is non-<code>null</code>
    
     */
    public static boolean isAlphanumeric(String str)
    {
        if (str == null) {
            return false;
        }
        for (int i = str.length() - 1; i >= 0; i--) {
            if (!Character.isLetterOrDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }


    /**
     * Checks and answers if the given string contains only
     * unicode letters or digits or space (' ').
     * <code>null</code> returns false,
     * an empty string ("") returns <code>true</code>.
     *
     * <pre>
     * StringVerification.isAlphanumericSpace(null)   == false
     * StringVerification.isAlphanumericSpace("")     == true
     * StringVerification.isAlphanumericSpace("   ")  == true
     * StringVerification.isAlphanumericSpace("abc")  == true
     * StringVerification.isAlphanumericSpace("ab c") == true
     * StringVerification.isAlphanumericSpace("ab2c") == true
     * StringVerification.isAlphanumericSpace("ab-c") == false
     * StringVerification.isAlphanumericSpace("123")  == true
     * StringVerification.isAlphanumericSpace("12 3") == true
     * StringVerification.isAlphanumericSpace("12-3") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string contains only unicode letters,
     *     digits or space (' '), and is non-<code>null</code>
    
     */
    public static boolean isAlphanumericSpace(String str)
    {
        if (str == null) {
            return false;
        }
        for (int i = str.length() - 1; i >= 0; i--) {
            char c = str.charAt(i);
            if (!Character.isLetterOrDigit(c) && (c != ' ')) {
                return false;
            }
        }
        return true;
    }


    /**
     * Checks and answers if the given string contains only unicode digits.
     * A decimal point is not a unicode digit and returns <code>false</code>.
     * <code>null</code> returns false,
     * an empty string ("") returns <code>true</code>.
     *
     * <pre>
     * StringVerification.isNumeric(null)   == false
     * StringVerification.isNumeric("")     == true
     * StringVerification.isNumeric("   ")  == false
     * StringVerification.isNumeric("abc")  == false
     * StringVerification.isNumeric("ab c") == false
     * StringVerification.isNumeric("ab2c") == false
     * StringVerification.isNumeric("ab-c") == false
     * StringVerification.isNumeric("123")  == true
     * StringVerification.isNumeric("12 3") == false
     * StringVerification.isNumeric("12-3") == false
     * StringVerification.isNumeric("12.3") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string contains only unicode digits,
     *     and is non-<code>null</code>
    
     */
    public static boolean isNumeric(String str)
    {
        if (str == null) {
            return false;
        }
        for (int i = str.length() - 1; i >= 0; i--) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }


    /**
     * Checks and answers if the given string contains only unicode digits
     * or space (' '). A decimal point is not a unicode digit and
     * returns <code>false</code>.
     * <code>null</code> returns false,
     * an empty string ("") returns <code>true</code>.
     *
     * <pre>
     * StringVerification.isNumericSpace(null)   == false
     * StringVerification.isNumericSpace("")     == true
     * StringVerification.isNumericSpace("   ")  == true
     * StringVerification.isNumericSpace("abc")  == false
     * StringVerification.isNumericSpace("ab c") == false
     * StringVerification.isNumericSpace("ab2c") == false
     * StringVerification.isNumericSpace("ab-c") == false
     * StringVerification.isNumericSpace("123")  == true
     * StringVerification.isNumericSpace("12 3") == true
     * StringVerification.isNumericSpace("12-3") == false
     * StringVerification.isNumericSpace("12.3") == false
     * </pre>
     *
     * @param str   the string to check, may be <code>null</code>
     * @return <code>true</code> if the string contains only unicode digits
     *     or space, and is non-<code>null</code>
    
     */
    public static boolean isNumericSpace(String str)
    {
        if (str == null) {
            return false;
        }
        for (int i = str.length() - 1; i >= 0; i--) {
            char c = str.charAt(i);
            if (!Character.isDigit(c) && (c != ' ')) {
                return false;
            }
        }
        return true;
    }


    public static boolean isExistInArray(String[] src,
                                         String str)
    {
        if (src == null) {
            return false;
        }
        else if (str == null) {
            return false;
        }
        for (int idx = 0; idx < src.length; idx++) {
            String elem = src[idx];
            if (str.equals(elem)) {
                return true;
            }
            else if (str.contains(elem)) {
                return true;
            }
        }
        return false;
    }


    public static boolean isExistInArray(String[] src,
                                         String str,
                                         String regexSeperator)
    {
        if (src == null) {
            return false;
        }
        else if (str == null) {
            return false;
        }
        else if (regexSeperator == null) {
            return false;
        }
        for (int idx = 0; idx < src.length; idx++) {
            String elem = src[idx];
            if (elem.startsWith(regexSeperator)) {
                String regex = elem.replace(regexSeperator,
                                            "");
                if (checkRegex(str,
                               regex)) {
                    return true;

                }
            }
            else if (str.equals(elem)) {
                return true;
            }
            else if (elem.equals("")) {
                return false;
            }
        }
        return false;
    }


    public static boolean checkRegex(String str,
                                     String regex)
    {
        if (str == null) {
            return false;
        }
        else if (regex == null) {
            return false;
        }
       String newStr=new String(str.replace("\r", " "));
        newStr=newStr.replace("\r\n", " ");
        newStr=newStr.replace("\n", " ");
        return  Pattern.compile(regex,Pattern.MULTILINE).matcher(newStr).matches();
    }


    public static boolean verifyText(String valToVerify,
                                     String currentVal)
    {
        boolean expectedVerificationValue = true;
        if(currentVal!=null)
            currentVal=currentVal.trim();
        if (valToVerify.startsWith("!=")) {
            valToVerify = valToVerify.replace("!=",
                                              "");
            expectedVerificationValue = false;
        }

        String[] valuesToCompare = new String[1];
        valuesToCompare[0]=valToVerify;
        if(valToVerify.contains("||"))
                valuesToCompare = valToVerify.split( AtofModuleConstants.PARAM_SEP_OR_SPLIT_STR);
        boolean result =
            isExistInArray(valuesToCompare,
                           currentVal,
                           AtofModuleConstants.REGEX_DEFINITION_STR);
        if (result == expectedVerificationValue) {
            return true;
        }
        return false;

    }
}
